#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System.Collections;

namespace CchenSoft.Workflow
{
    /**
     * Exception to indicate the user input is invalid. Handles both general errors and errors specific to an input.
     */
    public class InvalidInputException : WorkflowException
    {
        //~ Instance fields ////////////////////////////////////////////////////////

        private IList genericErrors = new ArrayList();
        private IDictionary errors = new Hashtable();

        //~ Constructors ///////////////////////////////////////////////////////////

        public InvalidInputException()
            :
            base()
        {
        }

        /**
         * Creates a new exception using the supplied Object
         * as a generic base. If the object is an instance of
         * this exception, all properties are copied to this
         * exception. If the object is an instance of Map or
         * String[], an errorName->errorMessage mapping will
         * be attempted to be extracted. If the object is
         * something else, it's toString() method will be
         * called and added as a single generic error.
         *
         * @param o the object
         */
        public InvalidInputException(object o)
        {
            if (o is InvalidInputException)
            {
                InvalidInputException iie = (InvalidInputException)o;
                errors = iie.getErrors();
                genericErrors = iie.getGenericErrors();
            }
            else if (o is IDictionary)
            {
                errors = (Hashtable)o;
            }
            else if (o is string[])
            {
                string[] stringMap = (string[])o;
                int length = stringMap.Length;
                string name = null;

                for (int i = 0; i < length; i++)
                {
                    if ((i % 2) == 0)
                    {
                        name = stringMap[i];
                    }
                    else
                    {
                        AddError(name, stringMap[i]);
                    }
                }
            }
            else
            {
                AddError(o.ToString());
            }
        }

        /**
         * Creates a new exception with an associated generic error.
         *
         * @param error a generic error message
         */
        public InvalidInputException(string error)
            :
            base(error)
        {
            AddError(error);
        }

        /**
         * Creates a new exception with an error specific to an input.
         *
         * @param name the input name that contains the error
         * @param error an error about the given name
         */
        public InvalidInputException(string name, string error)
            :
            base()
        {
            AddError(name, error);
        }

        //~ Methods ////////////////////////////////////////////////////////////////

        /**
         * Returns a map (String->String) of the input-specific errors.
         *
         * @return a map (String->String) of the input-specific errors
         */
        public IDictionary getErrors()
        {
            return errors;
        }

        /**
         * Returns a list (String) of generic errors.
         */
        public IList getGenericErrors()
        {
            return genericErrors;
        }

        /**
         * Adds a generic error.
         *
         * @param error the generic error message
         */
        public void AddError(string error)
        {
            genericErrors.Add(error);
        }

        /**
         * Adds an input-specific error.
         *
         * @param name the name of the input
         * @param error the error message
         */
        public void AddError(string name, string error)
        {
            errors.Add(name, error);
        }

        public override string ToString()
        {
            return "[InvalidInputException: [Error map: [" + errors + "]] [Error list: [" + genericErrors + "]]";
        }
    }
}
